#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
差旅费票据信息分析脚本

此脚本用于分析差旅费票据信息中的重复发票情况：
1. 筛选出【发票号码】相同，但【唯一标识】不同的数据
2. 筛选出【唯一标识】、【发票人员名称】、【发票号码】都相同的数据
"""

import pandas as pd
from pathlib import Path

# 配置常量
DATA_DIR = Path("data")
OUTPUT_DIR = DATA_DIR / "alldata"  # 输出目录
INVOICE_FILE = DATA_DIR / "差旅费票据信息.xlsx"
OUTPUT_FILE = OUTPUT_DIR / "发票重复分析结果.xlsx"

def clean_invoice_number(invoice_num):
    """
    清理发票号码数据
    
    Args:
        invoice_num: 原始发票号码数据，可能是字符串、数字或NaN
        
    Returns:
        str: 清理后的发票号码
    """
    if pd.isna(invoice_num):
        return ""
    return str(invoice_num).strip()

def clean_amount(amount):
    """
    清理并转换金额数据为浮点数
    
    Args:
        amount: 原始金额数据，可能是字符串、数字或NaN
        
    Returns:
        float: 清理后的金额数值
    """
    if pd.isna(amount):
        return 0.0
    if isinstance(amount, str):
        # 移除逗号和空格
        cleaned_amount = amount.replace(",", "").strip()
        try:
            return float(cleaned_amount)
        except ValueError:
            return 0.0
    return float(amount)

def find_duplicate_invoices_different_ids(df):
    """
    查找发票号码相同但唯一标识不同的记录
    
    Args:
        df (pd.DataFrame): 原始数据框
        
    Returns:
        pd.DataFrame: 筛选后的数据框
    """
    # 按发票号码分组，找出出现次数大于1且唯一标识不同的记录
    invoice_groups = df.groupby('发票号码').agg({
        '唯一标识': lambda x: len(set(x))
    }).reset_index()
    
    duplicate_invoices = invoice_groups[invoice_groups['唯一标识'] > 1]['发票号码']
    
    # 获取这些发票号码对应的完整记录
    result = df[df['发票号码'].isin(duplicate_invoices)].sort_values('发票号码')
    
    # 添加问题类型标识
    result['问题类型'] = '发票号码重复'
    
    return result

def find_completely_duplicate_invoices(df):
    """
    查找唯一标识、发票人员名称、发票号码都相同的记录
    
    Args:
        df (pd.DataFrame): 原始数据框
        
    Returns:
        pd.DataFrame: 筛选后的数据框
    """
    # 按三个字段分组，找出重复记录
    duplicate_mask = df.duplicated(
        subset=['唯一标识', '发票人员名称', '发票号码'], 
        keep=False
    )
    
    result = df[duplicate_mask].sort_values(['唯一标识', '发票人员名称', '发票号码'])
    
    # 添加问题类型标识
    result['问题类型'] = '完全重复'
    
    return result

def save_to_excel(results_dict, output_file, once):
    """
    将所有结果保存到一个Excel文件中
    
    Args:
        results_dict (dict): 包含结果数据框的字典
        output_file (Path): 输出文件路径
    """
    # 合并所有结果
    combined_results = pd.concat(results_dict.values(), ignore_index=True)
    
    # 调整列顺序，确保问题类型在前面
    columns = ['问题类型'] + [col for col in combined_results.columns if col != '问题类型']
    combined_results = combined_results[columns]

    if once:
        return combined_results
    # 保存到Excel
    combined_results.to_excel(output_file, index=False, sheet_name='发票重复问题', engine='openpyxl')

def main(once = False):
    """主程序入口"""
    try:
        # 确保输出目录存在
        OUTPUT_DIR.mkdir(parents=True, exist_ok=True)
        
        # 读取数据文件
        print("正在读取数据文件...")
        df = pd.read_excel(INVOICE_FILE, engine='openpyxl')
        
        # 数据预处理
        print("正在处理数据...")
        
        # 清理发票号码
        df['发票号码'] = df['发票号码'].apply(clean_invoice_number)
        
        # 清理金额
        df['发票金额'] = df['发票金额'].apply(clean_amount)
        
        # 基础过滤：移除发票金额为0和发票号码为空的记录
        df = df[
            (df['发票金额'] > 0) & 
            (df['发票号码'] != "")
        ]
        
        results = {}
        
        # 分析1：找出发票号码相同但唯一标识不同的记录
        print("\n正在分析发票号码重复情况...")
        duplicate_invoices = find_duplicate_invoices_different_ids(df)
        results['发票号码重复'] = duplicate_invoices
        print(f"发现 {len(duplicate_invoices)} 条发票号码重复记录")
        
        # 分析2：找出完全重复的记录
        print("\n正在分析完全重复记录...")
        complete_duplicates = find_completely_duplicate_invoices(df)
        results['完全重复'] = complete_duplicates
        print(f"发现 {len(complete_duplicates)} 条完全重复记录")

        # 保存结果
        print("\n正在保存分析结果...")
        data = save_to_excel(results, OUTPUT_FILE, once)
        if once:
            return data
        print(f"结果已保存至: {OUTPUT_FILE}")
        print(f"总计发现 {len(duplicate_invoices) + len(complete_duplicates)} 条问题记录")
        
    except FileNotFoundError:
        print(f"错误：找不到数据文件 {INVOICE_FILE}")
    except Exception as e:
        print(f"处理过程中出现错误: {str(e)}")
        raise

if __name__ == "__main__":
    main() 